// 可索引的类型
// 与使用接口描述函数类型差不多 我们也可以描述那些能够 通过索引得到的类型
// 可索引类型具有一个索引签名，它描述了对象索引的类型 还有响应的索引返回值类型
interface StringArray {
    [index: number]: string
}

let myArray: StringArray
myArray = ["Bob", "Fred"]

let myStr: string = myArray[0]
console.log(myStr)

// TS 支持两种索引签名：字符串和数字  可以同时使用两种类型的索引
// 但是数字索引的返回值必须是字符串索引返回值类型的子类型
// 这是因为当使用 number 来索引时，JS 会将它转换成 string 然后再去索引对象
// 也就是说 用 100 (一个number)去索引等同于使用 "100"(一个string)去索引
class Animal {
    name: string

    constructor(name: string) {
        this.name = name
    }
}

class Dog extends Animal {
    breed: string
    constructor(name: string, breed: string) {
        super(name)
        this.breed = breed
    }
}

// 错误：使用数值型的字符串索引，有时会得到完全不同的Animal!
interface NotOkay {
    // [x: number]: Animal;
    [x: string]: Dog;
}

// 字符串索引能够很好的描述 dictionary 模式，并且他们也会确保所有属性与其返回值类型相匹配
// 因为字符串索引声明了 obj.property 和 obj['property] 两种形式都可以

// 可以将索引签名设置为只读，这样就防止了给索引赋值：
interface ReadonlyStringArray {
    readonly [index: number]: string;
}
let myArray2: ReadonlyStringArray = ["Alice", "Bob"];
// myArray2[2] = "Mallory"; // error!